#ifndef LEXEMSTORAGE_H
#define LEXEMSTORAGE_H

#include <stddef.h>
#include <assert.h>
#include <stdio.h>

class LexemStorage {
  private:
    size_t maxSize;
    char* data;
    char* start;
    char* current;
    size_t freeSpace;

    char* createBlock(char*& space, size_t size) {
      space = new char[sizeof(char*) + size];  // pointer saved in beginning

      assert(space != NULL && "LexemStorrage constructor failed");

      *((char**)space) = NULL;  // pointer to next array
      return &(space[sizeof(char*)]);
    };

  public:
    LexemStorage(size_t size = 1024): maxSize(size),freeSpace(0) {
      start = NULL;
      start = createBlock(data, size);

      assert(*(char**)data == NULL && "NULL Pointer write failed");
      assert(*((char**)(start - sizeof(char*))) == NULL && "NULL Pointer write failed #2");

      current = data;
    }

    ~LexemStorage() {
      char* next;
      char* block = data;

      while(block != NULL) {
        next = *((char**)block);
        delete[] block;
        block = next;
      }
    }

    // allocates space
    char* malloc(size_t size) {
      if (freeSpace + size <= maxSize) {
        char* result = &start[freeSpace];
        freeSpace += size;
        return result;
      }
      else {
        while(maxSize < size) {
          maxSize *= 2;
        }
        char* newData;
        start = createBlock(newData, maxSize);

        *((char**)current) = newData;
        current = newData;

        freeSpace = 0;
        char* result = &start[freeSpace];
        freeSpace += size;
        return result;
      }
    }

    // frees space
    void free(char* ptr) {
      // not used
    }
};

#endif
